using System;
using System.Diagnostics;
using System.IO;


namespace Maxima.Common
{
    /// <summary>
    /// This class is for logging messages in file or console.
    /// Whatever - Just that I am hating this logger. This is bullish/shitish. Please excuse.
    /// TODO: Replace with Log4Net or default event viewer log mechanism.
    /// 
    /// 
    /// Btw, just another thought: What is the difference between CLogger and AppLog?! WTF!
    /// 
    /// Sorry, reader, just that I am looking into my own code after years, and well, just that just realized - how troubled I(and this code) was.
    /// </summary>
    public class CLogger
    {
        #region Constants and Variable Declaration

        private static string LOG_TIME_FORMAT = "dd.MM.yyyy HH:mm:ss";
        private string DEFAULT_LOG_PATH = System.AppDomain.CurrentDomain.BaseDirectory;
        private string DEFAULT_LOG_FILENAME = "iSIM";
        private string DEFAULT_EVENTLOG_SOURCE = "iSIM";
        private string DEFAULT_WRITER_NAME = "iSIM";
        private string DEFAULT_EVENTLOG_NAME = "iSIM";
        private int SEVERITY_LEVEL = 4;
        private static CLogger staticLogger = null;
        private const string CRLF = " ";
        private const string EXT = ".txt";

        private TextWriterTraceListener objTextWriterListener = null;

        private TraceLevel m_severityLevel;
        private DateTime FileDate = DateTime.Now;
        //private TextBox AppLogTextBox;

        #endregion


        #region getters and setters


        public string LogPath
        {
            set
            {
                if (value != null)
                {
                    DEFAULT_LOG_PATH = value;
                }
            }
            get
            {
                return DEFAULT_LOG_PATH;
            }
        }


        public string LogFileName
        {
            set
            {
                if (value != null)
                {
                    DEFAULT_LOG_FILENAME = value;
                }
            }
            get
            {
                return DEFAULT_LOG_FILENAME;
            }
        }

        public string TraceEventSource
        {
            set
            {
                if (value != null)
                {
                    DEFAULT_EVENTLOG_SOURCE = value;
                }
            }
            get
            {
                return DEFAULT_EVENTLOG_SOURCE;
            }
        }

        public int DebugLevel
        {
            get
            {
                return SEVERITY_LEVEL;
            }
        }

        #endregion


        public static CLogger GetInstance()
        {
            if (staticLogger == null)
            {
                CLogger objLogger = new CLogger();
                staticLogger = objLogger;
                return staticLogger;
            }
            else { return staticLogger; }
        }

        public static CLogger getInstanceTextObj()
        {
            CLogger objLogger = new CLogger();
            staticLogger = objLogger;
            //staticLogger.AppLogTextBox=Applog;
            return staticLogger;


        }

        private CLogger()
        {
            // Set default severity level
            m_severityLevel = TraceLevel.Warning;

            // Attempt to set the severity level from system parameters
            try
            {
                string logLevel = "Verbose";
                if (CConfigurator.ParamValue("LOG_SEVERITY_LEVEL") != null && !(CConfigurator.ParamValue("LOG_SEVERITY_LEVEL").Equals("")))
                {
                    logLevel = CConfigurator.ParamValue("LOG_SEVERITY_LEVEL");
                }

                setDebugLevel(logLevel);
            }
            catch (Exception e)
            {
                m_severityLevel = TraceLevel.Verbose;
            }

            // Initlistners Code
            if (Trace.Listeners[DEFAULT_WRITER_NAME] == null)
            {
                string LogFileName = DEFAULT_LOG_FILENAME;
                string LogPath = DEFAULT_LOG_PATH;

                if (CConstants.LOGFILENAME != null && CConstants.LOGPATH != null)
                {
                    LogFileName = CConstants.LOGFILENAME;
                    LogPath = CConstants.LOGPATH;
                }
                DateTime date = DateTime.Now;
                string FDate = date.Year.ToString() + date.Month.ToString().PadLeft(2, '0');//Keep year and month only - 1 year retention period.

                string FullyQualifiedFileName = LogPath + LogFileName + FDate + EXT;

                objTextWriterListener = new TextWriterTraceListener(FullyQualifiedFileName);

                Trace.Listeners.Add(objTextWriterListener);
                Trace.AutoFlush = true;

                
            }

            // End
        }

        /// <summary>
        /// Check the provided severity level and set the level in the logger 
        /// </summary>
        /// <param name="logLevel"></param>
        public void setDebugLevel(string logLevel)
        {

            if (logLevel.Equals("Off"))
            {
                m_severityLevel = TraceLevel.Off;
                SEVERITY_LEVEL = 0;
            }
            else if (logLevel.Equals("Error"))
            {
                m_severityLevel = TraceLevel.Error;
                SEVERITY_LEVEL = 1;
            }
            else if (logLevel.Equals("Warning"))
            {
                m_severityLevel = TraceLevel.Warning;
                SEVERITY_LEVEL = 2;
            }
            else if (logLevel.Equals("Info"))
            {
                m_severityLevel = TraceLevel.Info;
                SEVERITY_LEVEL = 3;
            }
            else if (logLevel.Equals("Verbose"))
            {
                m_severityLevel = TraceLevel.Verbose;
                SEVERITY_LEVEL = 4;
            }
            else
            {
                m_severityLevel = TraceLevel.Verbose;
                SEVERITY_LEVEL = 4;
            }
        }

        /// <summary>
        /// Check the provided severity level and set the level in the logger 
        /// </summary>
        /// <param name="logLevel"></param>
        public void SetDebugLevel(int logLevel)
        {
            SEVERITY_LEVEL = logLevel;
            if (logLevel == 0)
            {
                m_severityLevel = TraceLevel.Off;

            }
            else if (logLevel == 1)
            {
                m_severityLevel = TraceLevel.Error;
                SEVERITY_LEVEL = 1;
            }
            else if (logLevel == 2)
            {
                m_severityLevel = TraceLevel.Warning;
            }
            else if (logLevel == 3)
            {
                m_severityLevel = TraceLevel.Info;
            }
            else if (logLevel == 4)
            {
                m_severityLevel = TraceLevel.Verbose;
            }
            else
            {
                m_severityLevel = TraceLevel.Verbose;
                SEVERITY_LEVEL = 4;
            }
        }

        /// <summary>
        /// This method will load and initialize the trace listneres 
        /// </summary>
        public void InitTraceListeners()
        {
            if (Trace.Listeners[DEFAULT_WRITER_NAME] == null)
            {
                string LogFileName = DEFAULT_LOG_FILENAME;
                string LogPath = DEFAULT_LOG_PATH;

                if (CConstants.LOGFILENAME != null && CConstants.LOGPATH != null)
                {
                    LogFileName = CConstants.LOGFILENAME;
                    LogPath = CConstants.LOGPATH;
                }
                DateTime date = DateTime.Now;
                string FDate = date.Year.ToString() + date.Month.ToString().PadLeft(2, '0') + date.Day.ToString().PadLeft(2, '0');

                string FullyQualifiedFileName = LogPath + LogFileName + FDate + EXT;

                if (FileDate.Date != date.Date)
                {
                    FileDate = DateTime.Now;

                    Trace.Listeners.Clear();
                    Trace.AutoFlush = false;

                    objTextWriterListener = new TextWriterTraceListener(FullyQualifiedFileName);

                    Trace.Listeners.Remove(objTextWriterListener);

                    Trace.Listeners.Add(objTextWriterListener);
                    Trace.AutoFlush = true;
                }
            }
        }

        /// <summary>
        /// This method will remove the TextWriter Listener from Trace Listeners List 
        /// </summary>
        public void DisposeTraceListeners()
        {

            Trace.Listeners.Remove(objTextWriterListener);
            objTextWriterListener.Close();

        }

        /// <summary>
        /// This Method will write the Messages to Listners along with Module Name and Method Name
        /// </summary>
        /// <param name="severity">Message Severity: Will be used to check whether to log the message or not based on the severity level found in web.Constants</param>
        /// <param name="methodName">Method Name</param>
        /// <param name="message">Message String</param>
        public void Log(System.Diagnostics.TraceLevel severity, string moduleName, string methodName, string message)
        {
            string strLogMessage = "";
            if (m_severityLevel >= severity)
            {
                Trace.IndentSize = 4;
                strLogMessage = DateTime.Now.ToString(LOG_TIME_FORMAT) + " | " + String.Format("{0,-7}|{1,-12}|{2,-15}| ", severity, moduleName, methodName) + message;
                Trace.WriteLine(strLogMessage);
                //AppLogTextBox.Text+=strLogMessage+"\r\n";
            }

        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="severity"></param>
        public void Log(string message, System.Diagnostics.TraceLevel severity)
        {

            if (m_severityLevel >= severity)
                Trace.WriteLine(DateTime.Now.ToString(LOG_TIME_FORMAT) + " " + message + CRLF);

        }

        #region Logging Methods
        /// <summary>
        /// This method will be used for logging Debug/Info Messages
        /// </summary>
        /// <param name="message"></param>
        public void Debug(string aModuleName, string aMethodName, string aMessage)
        {
            string infoLogging = CConstants.INFO_LOGGING;
            if (infoLogging == "1")
            {
                //InitTraceListeners();
                this.Log(System.Diagnostics.TraceLevel.Info, aModuleName, aMethodName, aMessage);
            }

        }

        public void Debug(string aModuleName, string aMethodName, string aMessage, System.Diagnostics.EventLogEntryType type)
        {
            Debug(aModuleName, aMethodName, aMessage);
        }


        /// <summary>
        /// This method will be used for logging Error Messages
        /// </summary>
        /// <param name="message"></param>
        public void Error(string aModuleName, string aMethodName, string aMessage)
        {
            string errorLogging = CConstants.ERROR_LOGGING;
            if (errorLogging == "1")
            {
                //InitTraceListeners();
                this.Log(System.Diagnostics.TraceLevel.Error, aModuleName, aMethodName, aMessage);
            }
        }

        /// <summary>
        /// This method will be used for logging Error Messages
        /// </summary>
        /// <param name="message"></param>
        public void Error(string aModuleName, string aMethodName, Exception error)
        {
            //InitTraceListeners();
            this.Log(System.Diagnostics.TraceLevel.Error, aModuleName, aMethodName, error.StackTrace);

        }

        public void Error(string aModuleName, string aMethodName, string strCustomError, Exception error)
        {
            //InitTraceListeners();

            this.Log(System.Diagnostics.TraceLevel.Error, aModuleName, aMethodName, "ERROR: " + strCustomError + Environment.NewLine + "DESCRIPTION:" + Environment.NewLine + error.StackTrace);

        }
        /// <summary>
        /// This method will be used for logging Warning Messages
        /// </summary>
        /// <param name="message"></param>
        public void Warning(string aModuleName, string aMethodName, string aMessage)
        {
            //InitTraceListeners();
            this.Log(System.Diagnostics.TraceLevel.Warning, aModuleName, aMethodName, aMessage);
        }

        #endregion Logging Methods

    }

    public class AppLog
    {
        public static void setDebugLevel(string logLevel)
        {

            Common.CLogger.GetInstance().setDebugLevel(logLevel);
        }
        public static void InitTraceListeners()
        {
            Common.CLogger.GetInstance().InitTraceListeners();
        }
        public static void DisposeTraceListeners()
        {
            Common.CLogger.GetInstance().DisposeTraceListeners();
        }
        public static void Log(System.Diagnostics.TraceLevel severity, string moduleName, string methodName, string message)
        {
            Common.CLogger.GetInstance().Log(severity, moduleName, methodName, message);
        }
        public static void Log(string message, System.Diagnostics.TraceLevel severity)
        {
            Common.CLogger.GetInstance().Log(message, severity);
        }
        public static void Debug(string aModuleName, string aMethodName, string aMessage)
        {
            Common.CLogger.GetInstance().Debug(aModuleName, aMethodName, aMessage);
        }
        public static void Error(string aModuleName, string aMethodName, string aMessage)
        {
            Common.CLogger.GetInstance().Error(aModuleName, aMethodName, aMessage);
        }
        public static void Error(string aModuleName, string aMethodName, Exception error)
        {
            Common.CLogger.GetInstance().Error(aModuleName, aMethodName, error);
        }
        public static void Warning(string aModuleName, string aMethodName, string aMessage)
        {
            Common.CLogger.GetInstance().Warning(aModuleName, aMethodName, aMessage);
        }

        public static void Log(System.Diagnostics.TraceLevel severity, string message)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Log(severity, trace.GetFrame(1).GetMethod().DeclaringType.Name, trace.GetFrame(1).GetMethod().Name, message);
        }
        public static void Log(System.Diagnostics.TraceLevel severity)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Log(trace.GetFrame(1).GetMethod().Name, severity);
        }
        public static void Debug(string aMessage)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Debug(trace.GetFrame(1).GetMethod().DeclaringType.Name, trace.GetFrame(1).GetMethod().Name, aMessage);
        }
        public static void Error(string aMessage)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Error(trace.GetFrame(1).GetMethod().DeclaringType.Name, trace.GetFrame(1).GetMethod().Name, aMessage);
        }
        public static void Error(Exception error)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Error(trace.GetFrame(1).GetMethod().DeclaringType.Name, trace.GetFrame(1).GetMethod().Name, error);
        }
        public static void Warning(string aMessage)
        {
            StackTrace trace = new StackTrace();
            Common.CLogger.GetInstance().Warning(trace.GetFrame(1).GetMethod().DeclaringType.Name, trace.GetFrame(1).GetMethod().Name, aMessage);
        }
    }
}